package com.summer.boss.auth;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.summer.boss.constant.CommonConstants;
import com.summer.boss.enums.ResponseCodeEnum;
import com.summer.boss.properties.BossProperties;
import com.summer.boss.model.ResponseResult;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.UnsupportedJwtException;
import io.jsonwebtoken.security.SignatureException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * jwt认证
 * @author john
 */
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {

    @Resource
    private BossProperties properties;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
        // 不校验静态资源和swagger接口
        for (String ignore: properties.getAuth().getIgnoreSources()) {
            if (request.getRequestURI().contains(ignore)){
                chain.doFilter(request, response);
                return;
            }
        }

        String token = request.getHeader(properties.getAuth().getApiTokenHeader());
        // 测试token不校验
        if (CommonConstants.TOKEN.equals(token)) {
            chain.doFilter(request, response);
            return;
        }

        // 只认证,不鉴权
        try {
            JwtInfo jwtInfo = JwtUtil.getInfoFromToken(token);
            if (jwtInfo != null && StringUtils.hasText(jwtInfo.getUsername())) {
                // 设置安全上下文
                Authentication auth = this.getAuthentication(token);
                SecurityContextHolder.getContext().setAuthentication(auth);
                chain.doFilter(request, response);
            } else {
                response.getWriter().write(new ObjectMapper().writeValueAsString(ResponseResult.failure(ResponseCodeEnum.TOKEN_ERROR)));
            }
        } catch (ExpiredJwtException | UnsupportedJwtException | MalformedJwtException | SignatureException | IllegalArgumentException ex) {
            logger.error(ex);
            response.getWriter().write(new ObjectMapper().writeValueAsString(ResponseResult.failure(ResponseCodeEnum.TOKEN_ERROR)));
        } finally {
            SecurityContextHolder.clearContext();
        }

        // 把响应体写回到输出流(包装响应流)
//            ContentCachingResponseWrapper wrapperResponse = new ContentCachingResponseWrapper(response);
//            chain.doFilter(request, wrapperResponse);
//            wrapperResponse.copyBodyToResponse();
    }

    public Authentication getAuthentication(String token) {
        JwtInfo jwtInfo = JwtUtil.getInfoFromToken(token);
        return new UsernamePasswordAuthenticationToken(jwtInfo, token, null);
    }

}
